package com.lyfy.sd.order.controller;

import com.google.common.collect.Lists;
import com.lyfy.sd.order.dao.entity.OrderItemDetail;
import com.lyfy.sd.order.dao.entity.OrderMaster;
import com.lyfy.sd.order.dao.mapper.OrderItemDetailMapper;
import com.lyfy.sd.order.dao.mapper.OrderMasterMapper;
import com.lyfy.sd.order.vo.RespVo;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.curator.shaded.com.google.common.collect.Sets;
import org.apache.ibatis.session.RowBounds;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.WeekendSqls;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

import static com.lyfy.sd.order.constant.Constant.DEFAULT_CREATOR;
import static com.lyfy.sd.order.constant.Constant.DEFAULT_USER_ID;

/**
 * @author: 谢星星
 * @date: 2022/10/05 18:54
 * @description:
 */
@RestController
public class SdQueryController {

    @Resource
    private OrderMasterMapper orderMasterMapper;

    @Resource
    private OrderItemDetailMapper orderItemDetailMapper;

    /**
     * 场景：根据分片查询，会路由到指定节点上
     */
    @GetMapping(value = "sd/query-with-userid", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select1() {
        List<OrderMaster> orderMasters = orderMasterMapper.select(OrderMaster.builder()
                .userId(DEFAULT_USER_ID)
                .build());
        return RespVo.SUCCESS(orderMasters);
    }

    /**
     * 场景：根据非分片键查询，会广播到所有分片节点上查询，在分片节点上可以轮询查询
     */
    @GetMapping(value = "sd/query-with-creator", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select2() {
        List<OrderMaster> orderMasters = orderMasterMapper.select(OrderMaster.builder()
                .creator(DEFAULT_CREATOR)
                .build());
        return RespVo.SUCCESS(orderMasters);
    }

    /**
     * 场景：In查询分片键
     */
    @GetMapping(value = "sd/query-in-with-userid", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select3() {
        List<OrderMaster> orderMasters = orderMasterMapper.selectByExampleAndRowBounds(Example.builder(OrderMaster.class)
                .andWhere(WeekendSqls.<OrderMaster>custom()
                        .andIn(OrderMaster::getUserId, Lists.newArrayList(1L, DEFAULT_USER_ID)))
                .build(), new RowBounds(0, 10));
        return RespVo.SUCCESS(orderMasters);
    }

    /**
     * 场景：In查询非分片键
     */
    @GetMapping(value = "sd/query-in-with-creator", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select4() {
        List<OrderMaster> orderMasters = orderMasterMapper.selectByExampleAndRowBounds(Example.builder(OrderMaster.class)
                .andWhere(WeekendSqls.<OrderMaster>custom()
                        .andIn(OrderMaster::getCreator, Lists.newArrayList(DEFAULT_CREATOR)))
                .build(), new RowBounds(0, 10));
        return RespVo.SUCCESS(orderMasters);
    }


    /**
     * 场景：范围查询分片键，需要注意的是如果是分片键的范围查询，一定要自定义路由算法，不会默认广播至所有数据节点
     */
    @GetMapping(value = "sd/query-bt-with-userid", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select7() {
        List<OrderMaster> orderMasters = orderMasterMapper.selectByExampleAndRowBounds(Example.<OrderMaster>builder(OrderMaster.class)
                .andWhere(WeekendSqls.<OrderMaster>custom()
                        .andBetween(OrderMaster::getUserId, 1L, 10L))
                .build(), new RowBounds(0, 10));
        return RespVo.SUCCESS(orderMasters);
    }

    /**
     * 场景：范围查询非分片键，需要注意的是如果是非分片键的范围查询，不必自定义路由算法，默认采用广播路由方式
     */
    @GetMapping(value = "sd/query-bt-with-create_d", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select6() {
        Date end = new Date();
        Date start = DateUtils.addDays(end, -7);
        List<OrderMaster> orderMasters = orderMasterMapper.selectByExampleAndRowBounds(Example.<OrderMaster>builder(OrderMaster.class)
                .andWhere(WeekendSqls.<OrderMaster>custom()
                        .andBetween(OrderMaster::getCreateD, start, end))
                .build(), new RowBounds(0, 10));
        return RespVo.SUCCESS(orderMasters);
    }


    /**
     * 场景：在非分片键上做left join，采用广播路由方式，同时支持读写分离
     */
    @GetMapping(value = "sd/query-lj-omid", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select8() {
        List<OrderItemDetail> orderItemDetails = orderItemDetailMapper.getOrderItemDetailByOrderMasterId(1000L);
        return RespVo.SUCCESS(orderItemDetails);
    }


    /**
     * 场景：在分片键上路由基础上做left join，同时支持读写分离
     */
    @GetMapping(value = "sd/query-lj-userid", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select9() {
        List<OrderItemDetail> orderItemDetails = orderItemDetailMapper.getOrderItemDetailByUserId(DEFAULT_USER_ID);
        return RespVo.SUCCESS(orderItemDetails);
    }

    /**
     * 场景：分片键和非分片键的混合条件查询
     */
    @GetMapping(value = "sd/query-mix-cond", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select10() {
        List<OrderMaster> orderMasterList = orderMasterMapper.selectByExample(Example.builder(OrderMaster.class)
                .where(WeekendSqls.<OrderMaster>custom().andIn(OrderMaster::getUserId, Lists.newArrayList(1L, 4L)))
                .orWhere(WeekendSqls.<OrderMaster>custom().andEqualTo(OrderMaster::getOrderMasterId, 1000L))
                .build());
        return RespVo.SUCCESS(orderMasterList);
    }


    /**
     * 场景：分片键sum，left join，group by，having
     */
    @GetMapping(value = "sd/query-gb-hv-userid", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select11() {
        List<OrderItemDetailMapper.OrderMasterPayAmt> orderMasterPayAmts = orderItemDetailMapper.getOrderMasterPayAmtByUser(DEFAULT_USER_ID);
        return RespVo.SUCCESS(orderMasterPayAmts);
    }


    /**
     * 场景：非分片键sum，left join，group by，having
     */
    @GetMapping(value = "sd/query-gb-hv-omid", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select12() {
        List<OrderItemDetailMapper.OrderMasterPayAmt> orderMasterPayAmts = orderItemDetailMapper.getOrderMasterPayAmtById(Sets.newHashSet(1000L, 3074811977664967680L));
        return RespVo.SUCCESS(orderMasterPayAmts);
    }

    /**
     * 场景：分片键count
     */
    @GetMapping(value = "sd/query-count-userid", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select13() {
        int count = orderMasterMapper.selectCountByExample(Example.builder(OrderMaster.class)
                .where(WeekendSqls.<OrderMaster>custom().andEqualTo(OrderMaster::getUserId, DEFAULT_USER_ID))
                .build());
        return RespVo.SUCCESS(count);
    }


    /**
     * 场景：非分片键count
     */
    @GetMapping(value = "sd/query-count-creator", produces = MediaType.APPLICATION_JSON_VALUE)
    public RespVo select14() {
        int count = orderMasterMapper.selectCount(OrderMaster.builder()
                .creator(DEFAULT_CREATOR)
                .build());
        return RespVo.SUCCESS(count);
    }

}
